function extractLastSegment(path) {
    // 使用正则表达式匹配路径中的最后一个目录或文件名
    const regex = /\/([^/]+)\/?$/;
    const match = path.match(regex);

    // 如果有匹配，则返回匹配到的部分，否则返回空字符串
    if (match && match.length > 1) {
        return match[1];
    } else {
        return "";
    }
}

function escapeHtml(unsafe) {
    return unsafe
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#039;");
}

// 定义OneTabData结构体
class OneFileData {
    constructor(fileResult) {
        this.fileResult = fileResult;
        this.scrollPosition = 0;
    }
}

// 定义CodeViewData结构体
class CodeViewData {
    constructor() {
        this.token = "";
        this.activeFilePath = "";
        this.allOpenFileData = {};
        this.pathData = {};
        this.style = "./highlight/highlight.min.js";
    }

    saveStorage() {
        localStorage.setItem("token", this.token);
        localStorage.setItem("activeFilePath", this.activeFilePath);
        localStorage.setItem("pathData", JSON.stringify(this.pathData));
        localStorage.setItem("allOpenFileData", JSON.stringify(this.allOpenFileData));
        localStorage.setItem("style", this.style);
    }

    loadStorage() {
        if (localStorage.getItem("token") === null)
            return false;

        this.token = localStorage.getItem("token");
        this.allOpenFileData = JSON.parse(localStorage.getItem("allOpenFileData"));
        this.pathData = JSON.parse(localStorage.getItem("pathData"));
        this.activeFilePath = localStorage.getItem("activeFilePath");
        this.style = localStorage.getItem("style");
    }

    updateFrame() {
        let leftBar = document.getElementById('path-list-container');
        leftBar.innerHTML = '';
        addFolderPathItem(this.pathData);
        addFilePathItem(this.pathData);

        let tabsContainer = document.getElementById('tabs-container');
        tabsContainer.innerHTML = '';
        for (let filePath in this.allOpenFileData) {
            if (this.allOpenFileData.hasOwnProperty(filePath)) {
                addTab(this.allOpenFileData[filePath].fileResult);
            }
        }

        activateTab(this.activeFilePath);
        switchHighlightStyle(this.style);
    }

    reset() {
        this.token = "";
        this.activeFilePath = "";
        this.allOpenFileData = {};
        this.pathData = {};
        this.saveStorage();

        let leftBar = document.getElementById('path-list-container');
        leftBar.innerHTML = '';

        let tabsContainer = document.getElementById('tabs-container');
        tabsContainer.innerHTML = '';

        let showCode = document.getElementById('show-code');
        showCode.innerHTML = '';
    }

    addFileData(fileResult) {
        let filePath = fileResult.folder + "/" + fileResult.filename;
        this.allOpenFileData[filePath] = new OneFileData(fileResult);
        this.saveStorage();
        addTab(fileResult);
        // this.outDebugInfo();
        activateTab(filePath);
    }

    setPathData(folderResult) {
        this.pathData = folderResult;
        this.saveStorage();
        addFolderPathItem(folderResult);
        addFilePathItem(folderResult);
    }

    setToken(token) {
        this.token = token;
        this.saveStorage();
    }

    setActive(filePath) {
        this.activeFilePath = filePath;
        this.saveStorage();
    }

    setHighlightStyle(style) {
        this.style = style;
        this.saveStorage();
    }
    setScrollPosition(filePath, scrollPosition) {
        this.allOpenFileData[filePath].scrollPosition = scrollPosition;
        this.saveStorage();
    }

    getScrollPosition(filePath) {
        return this.allOpenFileData[filePath].scrollPosition;
    }

    getToken() {
        // console.log(this.token);
        return this.token;
    }

    getFileData(filePath) {
        return this.allOpenFileData[filePath].fileResult.data;
    }

    removeFileData(filePath) {
        delete this.allOpenFileData[filePath];
        this.saveStorage();
    }

    pathIsNull() {
        return this.pathData === null || this.pathData.main === undefined;
    }

    outDebugInfo() {
        for (let filePath in this.allOpenFileData) {
            if (this.allOpenFileData.hasOwnProperty(filePath)) {
                let fileData = this.allOpenFileData[filePath];
                console.log(filePath + " : " + fileData.scrollPosition);
            }
        }
    }
}

class WsCodeView {
    constructor() {
        console.log("window.location.href");
        this.ws = {};
        this.url = null;
        this.connectAttempts = 0;
        this.maxConnectAttempts = 5; // 最大重连次数
        this.connectDelay = 3000; // 重连延迟时间（毫秒）
    }

    connect(url) {
        this.url = url;
        this.ws = new WebSocket(url);

        this.ws.onopen = () => {
            console.log("WebSocket connected");
            this.ws.send("Login");
            this.ws.send(codeViewData.getToken());
        };

        this.ws.onmessage = (event) => {
            this.recvData(event);
        };

        this.ws.onclose = (event) => {
            console.log(`WebSocket closed: code=${event.code}, reason=${event.reason}`);
            if (event.code !== 1000) {
                this.reconnect();
            }
        };

        this.ws.onerror = (error) => {
            console.error("WebSocket error:", error);
            this.reconnect();
        };
    }

    reconnect() {
        if (this.connectAttempts < this.maxConnectAttempts) {
            console.log(`Attempting to reconnect (attempt ${this.connectAttempts + 1} of ${this.maxConnectAttempts})...`);
            setTimeout(() => {
                this.connect(this.url);
            }, this.connectDelay);
            this.connectAttempts++;
        } else {
            console.error(`Maximum reconnect attempts (${this.maxConnectAttempts}) reached. Stopping reconnect.`);
        }
    }

    recvData(event) {
        // console.log(event.data);
        let data = JSON.parse(event.data);
        if (data.cmd == "Login")
            this.recvLogin(data);
        else if (data.cmd == "Folder")
            this.recvFolder(data);
        else if (data.cmd == "File")
            this.recvFileData(data);
    }

    recvLogin(data) {
        if (data.result.msg == "success") {
            // console.log("checkPassword");
            document.getElementById('main-frame').classList.remove('hidden');
            document.getElementById('password-container').classList.add('hidden');

            setViewSize();

            codeViewData.setToken(data.result.token);
            if (codeViewData.pathIsNull()) {
                this.sendPath("");
            }
            else {
                codeViewData.updateFrame();
            }
            // this.sendPath("");
        }
        else {
            alert('Incorrect password!');
        }
    }

    recvFolder(data) {
        codeViewData.setPathData(data.result);
    }

    recvFileData(data) {
        codeViewData.addFileData(data.result);

        // let tabs = document.getElementById('tabs-container');
        // let viewContainer = document.getElementById('view-container');
        // let filePath = data.result.folder + "/" + data.result.filename;
        // let newTab = document.createElement('div');
        // newTab.className = 'tab';
        // newTab.id = filePath + "-tab";
        // console.log("tab id:" + newTab.id);
        // newTab.filePath = filePath;
        // newTab.innerHTML = `${data.result.filename} <span class="close-btn" onclick="closeTab(event, '${filePath}')">x</span>`;
        // newTab.onclick = function () { activateTab(filePath); };
        // tabs.appendChild(newTab);
        // activateTab(filePath);
    }

    sendLogin(pwd) {
        this.ws.send("Login");
        this.ws.send(pwd);
    }

    sendPath(path) {
        console.log("sendPath:" + path);
        this.ws.send("Path");
        this.ws.send(path);
    }
}


let codeViewData = new CodeViewData();
let wsCodeView = new WsCodeView();
let codeViewWidth = 0;
let codeViewHeight = 0;

window.onbeforeunload = function () {
    codeViewData.saveStorage();
    console.log("window.onbeforeunload");
}

window.onload = function () {
    codeViewData.loadStorage();
    // 获取当前页面的域名和端口
    let hostname = window.location.hostname; // 获取域名
    let port = window.location.port; // 获取端口
    console.log("hostname:" + hostname + " port:" + port);
    // 构建 WebSocket 地址
    console.log("ws:"+hostname + ":" + port);
    // wsCodeView.connect("wss://" + hostname + ":" + port + "/ws_wcv/");
    //wsCodeView.connect("ws://" + hostname + ":60004/");
    wsCodeView.connect("ws://127.0.0.1:60004/");
}

window.addEventListener('resize', function() {
    setViewSize();
});

function setViewSize() {

    let viewContainer = document.getElementById("view-container");
    let showCodePre = document.getElementById("show-code-pre");
    let showCode = document.getElementById("show-code");
    
    let viewFrame = document.getElementById("view-frame-container");
    // codeViewWidth = viewFrame.getBoundingClientRect().width;
    // codeViewHeight = viewFrame.getBoundingClientRect().height;
    codeViewWidth = viewFrame.clientWidth;
    codeViewHeight = viewFrame.clientHeight;
    console.log("Current view width:", codeViewWidth, " height:", codeViewHeight);

    viewContainer.style.width = codeViewWidth + "px";
    viewContainer.style.height = codeViewHeight + "px";


    // performance.
}

function setBackgroundColor() {

    // console.log("setBackgroundColor");
    // let viewContainer = document.getElementById("view-container");
    // let showCodePre = document.getElementById("show-code-pre");
    // let showCode = document.getElementById("show-code");
    // console.log("showCode backgroundColor:" + window.getComputedStyle(showCode).backgroundColor);

    // viewContainer.style.backgroundColor = window.getComputedStyle(showCode).backgroundColor;
    // console.log("showCode backgroundColor:" + window.getComputedStyle(showCodePre).backgroundColor);
}

function addFolderPathItem(folderResult) {

    let leftBar = document.getElementById('path-list-container');
    leftBar.innerHTML = '';

    let newItemPath = document.createElement('div');
    newItemPath.className = 'folder-item';
    newItemPath.id = "parent-path-item";
    newItemPath.filePath = folderResult.parent;
    newItemPath.onclick = function () { onclickFloderPathItem(folderResult.parent); };
    newItemPath.innerHTML = `<img src="./image/folder.svg" alt="SVG Icon">..`;
    leftBar.appendChild(newItemPath);

    if (folderResult.folder === undefined || folderResult.folder.length == 0) {
        return;
    }

    // 获取输入框元素
    let inputElement = document.getElementById('filter-input');

    // 获取用户输入的值
    let filterStr = inputElement.value;

    folderResult.folder.sort();
    for (let i = 0; i < folderResult.folder.length; ++i) {
        // console.log("fileName:" + folderResult.folder[i]);
        // console.log("filterStr:" + filterStr);
        // console.log("filePath.indexOf(filterStr):" + folderResult.folder[i].indexOf(filterStr));
        // console.log("val:" + (filterStr.length > 0 && folderResult.folder[i].indexOf(filterStr) == -1));
        if(filterStr.length > 0 && folderResult.folder[i].indexOf(filterStr) == -1)
            continue;
        
        let filePath = folderResult.main + "/" + folderResult.folder[i];
        let newItemPath = document.createElement('div');
        newItemPath.className = 'folder-item';
        newItemPath.id = filePath + "-path-item";
        newItemPath.filePath = filePath;
        newItemPath.onclick = function () { onclickFloderPathItem(filePath); };
        newItemPath.innerHTML = `<img src="./image/folder.svg" alt="SVG Icon">${folderResult.folder[i]}`;
        leftBar.appendChild(newItemPath);
    }
}

function addFilePathItem(folderResult) {
    if (folderResult.file === undefined || folderResult.file.length == 0) {
        return;
    }
    let leftBar = document.getElementById('path-list-container');

    // 获取输入框元素
    let inputElement = document.getElementById('filter-input');

    // 获取用户输入的值
    let filterStr = inputElement.value;

    folderResult.file.sort();
    for (let i = 0; i < folderResult.file.length; ++i) {
        
        if(filterStr.length > 0 && folderResult.file[i].indexOf(filterStr) == -1)
            continue;

        let filePath = folderResult.main + "/" + folderResult.file[i];
        let newItemPath = document.createElement('div');
        newItemPath.className = 'file-item';
        newItemPath.id = folderResult.main + "/" + folderResult.file[i] + "-path-item";
        newItemPath.filePath = filePath;
        newItemPath.onclick = function () { onclickFilePathItem(filePath); };
        newItemPath.innerHTML = `<img src="./image/file.svg" alt="SVG Icon">${folderResult.file[i]}`;
        leftBar.appendChild(newItemPath);
    }
}

function addTab(fileResult) {
    let tabContainer = document.getElementById('tabs-container');
    let viewContainer = document.getElementById('view-container');
    let filePath = fileResult.folder + "/" + fileResult.filename;
    let newTab = document.createElement('div');
    newTab.className = 'tab';
    newTab.id = filePath + "-tab";
    // console.log("tab id:" + newTab.id);
    newTab.filePath = filePath;
    newTab.innerHTML = `${fileResult.filename} <span class="close-btn" onclick="closeTab(event, '${filePath}')">X</span>`;
    newTab.onclick = function () { activateTab(filePath); };
    newTab.ondblclick = function (event) { closeTab(event, filePath); };
    tabContainer.appendChild(newTab);

    let tabS = document.getElementsByClassName('tab');
    // console.log("tabs.length :" + tabS.length );
    if (tabS.length > 10) {
        // activateTab(tabs[0], document.getElementById(tabs[0].id + '-content'), tabs[0].id);
        // console.log("remove tab:" + tabS[0].filePath);
        codeViewData.removeFileData(tabS[0].filePath);
        tabS[0].remove();
    }
}

function toggleLeftBar() {
    let container = document.getElementById('left-bar-container');
    if (container == null)
        console.log("container is null");
    container.classList.toggle('hidden');
    let toggleBtn = document.getElementById('toggle-left-bar-btn');
    toggleBtn.innerHTML = container.classList.contains('hidden') ? 'Show' : 'Hide';
    setViewSize();
}

function onclickFloderPathItem(path) {
    wsCodeView.sendPath(path);
}

function onclickFilePathItem(path) {
    
    let existingTab = document.getElementById(path + '-tab');
    if (existingTab) {
        // console.log("activateTab:" + path);
        activateTab(path);
    } else {
        // console.log("createTab:" + path);
        wsCodeView.sendPath(path);
    }
}

function activateTab(filePath) {

    let tab = document.getElementById(filePath + "-tab");
    let pathItem = document.getElementById(filePath + '-path-item');
    let viewFrame = document.getElementById("view-frame-container");
    let view = document.getElementById("view-container");
    let showCodePre = document.getElementById("show-code-pre");
    let showCode = document.getElementById("show-code");
    

    let i, tabS, pathItemS;
    tabS = document.getElementsByClassName('tab');
    for (i = 0; i < tabS.length; i++) {
        // if(tabS[i].classList.contains('active'))
        //     codeViewData.setScrollPosition(tabS[i].filePath, view.scrollTop);
        tabS[i].classList.remove('active');
    }

    pathItemS = document.getElementsByClassName('file-item');
    for (i = 0; i < pathItemS.length; i++) {
        pathItemS[i].classList.remove('active');
    }


    if (pathItem)
        pathItem.classList.add('active');

    if (tab) {
        
        tab.classList.add('active');

        showCode.innerHTML = filePath + "\n" + escapeHtml(codeViewData.getFileData(filePath));

        view.scrollTop = codeViewData.getScrollPosition(filePath);        
        codeViewData.setActive(filePath);

        document.getElementById('top-bar-title').innerHTML = escapeHtml(filePath);
        showCode.removeAttribute('data-highlighted');

        showCode.className = getlanguage(filePath);
        
        hljs.highlightElement(showCode);
        // 重新应用行号
        hljs.lineNumbersBlock(showCode);
        setBackgroundColor();

        console.log("view client:" + view.clientWidth + "," + view.clientHeight);
        console.log("view scroll:" + view.scrollWidth + "," + view.scrollHeight);
        console.log("showCodePre client:" + showCodePre.clientWidth + "," + showCodePre.clientHeight);
        console.log("showCodePre scroll:" + showCodePre.scrollWidth + "," + showCodePre.scrollHeight);
        console.log("showCode client:" + showCode.clientWidth + "," + showCode.clientHeight);
        console.log("showCode scroll:" + showCode.scrollWidth + "," + showCode.scrollHeight);
    }
}

function closeTab(event, filePath) {
    event.stopPropagation();
    console.log("closeTab:" + filePath);
    let tab = document.getElementById(filePath + "-tab");
    tab.remove();

    codeViewData.removeFileData(filePath);
    // console.log(JSON.stringify(codeViewData));

    let tabs = document.getElementsByClassName('tab');
    if (tabs.length > 0) {
        // activateTab(tabs[0], document.getElementById(tabs[0].id + '-content'), tabs[0].id);
        activateTab(tabs[0].filePath);
    }
    else {
        showCode = document.getElementById("show-code");
        showCode.innerHTML = "";
    }
}

function checkPassword() {
    // console.log("checkPassword");
    // document.getElementById('main-frame').classList.remove('hidden');
    let password = document.getElementById('password').value;
    wsCodeView.sendLogin(password);

    // if (password === correctPassword) {
    //     document.getElementById('main-frame').classList.remove('hidden');
    //     document.getElementById('password-container').classList.add('hidden');
    // } else {
    //     alert('Incorrect password!');
    // }
}

function switchHighlightStyle(style) {
    // console.log("switchHighlightStyle:" + style);
    // var link = document.getElementById('highlight-style');
    // link.href = style;
    // codeViewData.setHighlightStyle(style);
    // hljs.highlightElement(document.getElementById('show-code'));

    // setTimeout(function() {
    //     setBackgroundColor();
    //   }, 5); // 这里可以根据需要调整延迟的时间
    
}

function handleScroll() {
    view = document.getElementById("view-container");
    codeViewData.setScrollPosition(codeViewData.activeFilePath, view.scrollTop);
}

function resetCatch() {
    codeViewData.reset();
    wsCodeView.sendPath("");
}

function openSelectedFile(){
    let selection = window.getSelection();
    //获取选中的文本内容
    let selectedText = selection.toString();
    console.log(selectedText);
    if(codeViewData.activeFilePath.length ==0){
        return;
    }
    let fileFolder = codeViewData.allOpenFileData[codeViewData.activeFilePath].fileResult.folder;
    let openFile = fileFolder + "/" + selectedText;
    console.log(openFile);
    wsCodeView.sendPath(openFile);
}

function filterFiles() {
    addFolderPathItem(codeViewData.pathData);
    addFilePathItem(codeViewData.pathData);
}

function getlanguage(filePath)
{
    let fileTmp = filePath.toLowerCase();
    console.log(fileTmp);
    if (fileTmp.endsWith(".java")) {
        return "language-java";
    }
    else if (fileTmp.endsWith(".py")) {
        return "language-python";
    }
    else if (fileTmp.endsWith(".c")) {
        return "language-c";
    }
    else if (fileTmp.endsWith(".cpp") || fileTmp.endsWith(".h") || fileTmp.endsWith(".hpp")) {
        return "language-cpp";
    }
    else if (fileTmp.endsWith(".js")) {
        return "language-javascript";
    }
    else if (fileTmp.endsWith(".html")) {
        return "language-html";
    }
    else if (fileTmp.endsWith(".css")) {
        return "language-css";
    }
    else if (fileTmp.endsWith(".php")) {
        return "language-php";
    }
    else if (fileTmp.endsWith(".go")) {
        return "language-go";
    }
    else if (fileTmp.endsWith(".xml")) {
        return "language-xml";
    }
    else if (fileTmp.endsWith(".json")) {
        return "language-json";
    }
    else if (fileTmp.endsWith(".yaml")) {
        return "language-yaml";
    }
    else if (fileTmp.endsWith(".bash") || fileTmp.endsWith(".sh")) {
        return "language-bash";
    }
    else {
        return "language-cpp";
    }
}